library(tidyverse, verbose = F)
── Attaching core tidyverse packages ──────────────────────────────────────────────────────────────────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.1.4     ✔ readr     2.1.5
✔ forcats   1.0.0     ✔ stringr   1.5.1
✔ ggplot2   3.4.4     ✔ tibble    3.2.1
✔ lubridate 1.9.3     ✔ tidyr     1.3.1
✔ purrr     1.0.2     ── Conflicts ────────────────────────────────────────────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the ]8;;http://conflicted.r-lib.org/conflicted package]8;; to force all conflicts to become errors
source("Funciones.R")

Lectura de Datos

Lo datos corresponde a una matriz 5x5x10. La metadata será X = 1…25 y Z = 1…10 (profundidad), ambos detectores tienen la misma metadata.

##Metadata
Metadata <- data.frame(x = rep(1:100, each = 11), 
                       z = rep(1:11, 100))

Comp.data <- data.frame(muestra = c("ss406", "ss407", "ss408", "ss409", "ss410"), 
                        C = c(0.19,0.50,0.28,0.11,0.39),
                        Mn = c(0.53,0.13,0.64,0.48,0.43),
                        Ni = c(1.69,0.61,4.58,3.14,2.04),
                        Cr = c(2.12,3.00,0.09,1.22,1.72),
                        Mo = c(1.03,0.82,0.14,0.77,0.41),
                        Cu = c(0.32,0.43,0.73,0.23,0.47))

DEMON

data.dir <- "Data/demon/"

## DEMON data
L_Demon <- map(c("ss406.asc","ss407.asc","ss408.asc","ss409.asc","ss410.asc"), 
               ~ read_tsv(paste(data.dir,.x,sep = ""), col_names = F, progress = F, show_col_types = F)) 

L_Demon <- L_Demon %>% set_names(c("ss406","ss407","ss408","ss409","ss410"))  

L_Demon <- L_Demon %>% map(~ .x %>% setNames(c("wl",paste("X", 1:(ncol(.x)-1), sep = ""))))

## elimina shot 1
L_Demon <- L_Demon %>% 
  map(~ .x %>% .[, c(1, which(Metadata$z != 1) + 1)]) ## elimina disparo #1 (limpieza)

g <- L_Demon %>% map(~ data.frame(.x[,1], Int = apply(.x[,2:ncol(.x)], 1, mean))) %>% bind_rows(.id = "id") %>% 
  ggplot(aes(x = wl, y = Int, color = id)) + geom_line() + labs(x = "Wavelength")
g %>% plotly::ggplotly()
Registered S3 method overwritten by 'data.table':
  method           from
  print.data.table     
Registered S3 method overwritten by 'htmlwidgets':
  method           from         
  print.htmlwidget tools:rstudio
## Normalizar
izq <- 267.70
der <- 267.75
int <- L_Demon %>% map_dfr(fun.int, izq = izq, der = der)
factor <-  1
int_norm <- int/factor

## acumular
int_norm <- sumar_filas_por_grupos(int_norm, n = 10, wl = F)

## Promediar
int_norm <- cbind(Comp.data, int_norm)
int_norm %>% pivot_longer(X1:X100, values_to = "Libs.Int") %>%
  ggplot(aes(x = Libs.Int, y = Cr, color = muestra)) + 
    geom_point() + 
    geom_hline(yintercept = int_norm$Cr, lty = 2, col = "gray")


int_mean <- apply(int_norm %>% select(X1:X100), 1, promediar_grupos_aleatorios, n=10) %>% t() %>% data.frame()
int_mean <- cbind(Comp.data, int_mean)
int_mean %>% pivot_longer(X1:X10, values_to = "Libs.Int") %>% 
  ggplot(aes(x = Libs.Int, y = Cr, color = muestra)) + 
    geom_point() + 
    geom_hline(yintercept = int_norm$Cr, lty = 2, col = "gray")


int_mean %>% pivot_longer(X1:X10, values_to = "Libs.Int") %>% 
  ggplot(aes(x = Libs.Int, y = Cr, color = muestra)) + 
    geom_boxplot() + 
    geom_hline(yintercept = int_norm$Cr, lty = 2, col = "gray")

MECHELLE

data.dir <- "Data/mechelle/"
## Mechelle data
L_Mechelle <- map(c("ss406.asc","ss407.asc","ss408.asc","ss409.asc","ss410.asc"), 
                  ~ read_tsv(paste(data.dir,.x,sep = ""), col_names = F, progress = F, show_col_types = F)) 

L_Mechelle <- L_Mechelle %>% map(~ .x %>% setNames(c("wl",paste("X", 1:(ncol(.x)-1), sep = ""))))
L_Mechelle <- L_Mechelle %>% set_names(c("ss406","ss407","ss408","ss409","ss410"))  

Exploracion Cromo

## elimina shot 1
L_Mechelle <- L_Mechelle %>% 
  map(~ .x %>% .[, c(1, which(Metadata$z != 1) + 1)]) ## elimina disparo #1 (limpieza)

g <- L_Mechelle %>% map(~ data.frame(.x[,1], Int = apply(.x[,2:ncol(.x)], 1, mean))) %>% bind_rows(.id = "id") %>% 
  ggplot(aes(x = wl, y = Int, color = id)) + geom_line() + labs(x = "Wavelength")
g %>% plotly::ggplotly()
Registered S3 method overwritten by 'data.table':
  method           from
  print.data.table     
Registered S3 method overwritten by 'htmlwidgets':
  method           from         
  print.htmlwidget tools:rstudio

Wavelength Calibration

c
function (...)  .Primitive("c")

Normalizando por suma total 200-1000

Acumular (z) - Normalizar - Promediar (x)

## acumular
L <- L_Mechelle %>% map(~ .x %>% sumar_filas_por_grupos(n = 10))
  
## Normalizar
# izq <- 267.6567
# der <- 267.8053
#int <- L %>% map_dfr(fun.int, izq = izq, der = der)
int <- L %>% map_dfr(fun.int2, centro)
factor <- L %>% map_dfr(fun.int, izq = 200, der = 1030)
int_norm <- int/factor

## Promediar
int_norm <- cbind(Comp.data, int_norm)
int_norm %>% pivot_longer(X1:X100, values_to = "Libs.Int") %>% ggplot(aes(x = Libs.Int, y = Cr, color = muestra)) + geom_boxplot()

Normalizar - Acumular (z) - promediar (x)

## Normalizar
izq <- 267.6567
der <- 267.8053
int <- L_Mechelle %>% map_dfr(fun.int, izq = izq, der = der)
factor <- L_Mechelle %>% map_dfr(fun.int, izq = 200, der = 1030)
int_norm <- int/factor

## acumular
int_norm <- sumar_filas_por_grupos(int_norm, n = 10, wl = F)
  
## Promediar
int_norm <- cbind(Comp.data, int_norm)
int_norm %>% pivot_longer(X1:X25, values_to = "Libs.Int") %>% ggplot(aes(x = Libs.Int, y = Cr, color = muestra)) + geom_boxplot()

Normalizando por suma total 200-600

Acumular (z) - Normalizar - Promediar (x)

## acumular
L <- L_Mechelle %>% map(~ .x %>% sumar_filas_por_grupos(n = 10, wl = T))
  
## Normalizar
izq <- 267.6567
der <- 267.8053
int <- L %>% map_dfr(fun.int, izq = izq, der = der)
factor <- L %>% map_dfr(fun.int, izq = 200, der = 600)
int_norm <- int/factor

## Promediar
int_norm <- cbind(Comp.data, int_norm)
int_norm %>% pivot_longer(X1:X100, values_to = "Libs.Int") %>% 
  ggplot(aes(x = Libs.Int, y = Cr, color = muestra)) + geom_boxplot() + geom_hline(yintercept = int_norm$Cr, lty = 2, col = "gray")

int_mean <- apply(int_norm %>% select(X1:X100), 1, promediar_grupos_aleatorios, n=5) %>% data.frame()
int_mean <- cbind(Comp.data, int_mean)
int_norm %>% pivot_longer(X1:X10, values_to = "Libs.Int") %>% 
  ggplot(aes(x = Libs.Int, y = Cr, color = muestra)) + geom_boxplot() + geom_hline(yintercept = int_norm$Cr, lty = 2, col = "gray")

Normalizar - Acumular (z) - promediar (x)

## Normalizar
izq <- 267.6567
der <- 267.8053
int <- L_Mechelle %>% map_dfr(fun.int, izq = izq, der = der)
factor <- L_Mechelle %>% map_dfr(fun.int, izq = 200, der = 600)
int_norm <- int/factor

## acumular
int_norm <- sumar_filas_por_grupos(int_norm, n = 10, wl = F)

## Promediar
int_norm <- cbind(Comp.data, int_norm)
int_norm %>% pivot_longer(X1:X100, values_to = "Libs.Int") %>%
  ggplot(aes(x = Libs.Int, y = Cr, color = muestra)) + geom_point() + geom_hline(yintercept = int_norm$Cr, lty = 2, col = "gray")

int_mean <- apply(int_norm %>% select(X1:X100), 1, promediar_grupos_aleatorios, n=5) %>% data.frame()
int_mean <- cbind(Comp.data, int_mean)
int_norm %>% pivot_longer(X1:X5, values_to = "Libs.Int") %>% 
  ggplot(aes(x = Libs.Int, y = Cr, color = muestra)) + geom_point() + geom_hline(yintercept = int_norm$Cr, lty = 2, col = "gray")
## Normalizar
izq <- 283.49
der <- 283.65
int <- L_Mechelle %>% map_dfr(fun.int, izq = izq, der = der)
factor <- L_Mechelle %>% map_dfr(fun.int, izq = 200, der = 600)
int_norm <- int/factor

## acumular
int_norm <- sumar_filas_por_grupos(int_norm, n = 10, wl = F)

## Promediar
int_norm <- cbind(Comp.data, int_norm)
int_norm %>% pivot_longer(X1:X100, values_to = "Libs.Int") %>%
  ggplot(aes(x = Libs.Int, y = Cr, color = muestra)) + geom_point() + geom_hline(yintercept = int_norm$Cr, lty = 2, col = "gray") 

int_mean <- apply(int_norm %>% select(X1:X100), 1, promediar_grupos_aleatorios, n = 5) %>% data.frame()
int_mean <- cbind(Comp.data, int_mean)
int_mean %>% pivot_longer(X1:X5, values_to = "Libs.Int") %>% 
  ggplot(aes(x = Libs.Int, y = Cr, color = muestra)) + geom_point() + geom_hline(yintercept = int_norm$Cr, lty = 2, col = "gray")

Exploracion Aire - Argon

data.dir <- "Data/exp1/"
## Mechelle data Aire
L_Aire <- map(c("ss407_NoBL.asc","ss408_NoBL.asc"), 
                  ~ read_csv(paste(data.dir,.x,sep = ""), col_names = F, progress = F, show_col_types = F)) %>% 
  set_names(c("ss407_Aire","ss408_Aire"))

data.dir <- "Data/exp2/"
L_Argon <- map(c("ss407_Ar_NoBL.asc","ss408_Ar_NoBL.asc"), 
                  ~ read_csv(paste(data.dir,.x,sep = ""), col_names = F, progress = F, show_col_types = F)) %>% 
  set_names(c("ss407_Ar","ss408_Ar"))

L_Mechelle <- c(L_Aire, L_Argon) %>% map(~ .x %>% setNames(c("wl",paste("X", 1:(ncol(.x)-1), sep = ""))))

## Normalizar
izq <- 267.6567
der <- 267.8053
int <- L_Mechelle %>% map_dfr(fun.int, izq = izq, der = der)
factor <- L_Mechelle %>% map_dfr(fun.int, izq = 200, der = 600)
int_norm <- int/factor

## acumular
int_norm <- sumar_filas_por_grupos(int_norm, n = 25, wl = F)

## Promediar
metdata <- data.frame(muestra = c("ss407_Aire", "ss408_Aire", "ss407_Ar", "ss408_Ar")) %>% mutate(rbind(Comp.data[2:3,2:ncol(Comp.data)],Comp.data[2:3,2:ncol(Comp.data)]) )

int_norm <- cbind(metdata, int_norm)
int_norm %>% pivot_longer(X1:X25, values_to = "Libs.Int") %>%
  ggplot(aes(x = Libs.Int, y = Cr, color = muestra)) + geom_point() + geom_hline(yintercept = int_norm$Cr, lty = 2, col = "gray")

int_mean <- apply(int_norm %>% select(X1:X25), 1, promediar_grupos_aleatorios, n=5) %>% data.frame()
int_mean <- cbind(Comp.data, int_mean)
int_norm %>% pivot_longer(X1:X5, values_to = "Libs.Int") %>% 
  ggplot(aes(x = Libs.Int, y = Cr, color = muestra)) + geom_point() + geom_hline(yintercept = int_norm$Cr, lty = 2, col = "gray")
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQpgYGB7cn0NCmxpYnJhcnkodGlkeXZlcnNlLCB2ZXJib3NlID0gRikNCnNvdXJjZSgiRnVuY2lvbmVzLlIiKQ0KYGBgDQoNCiMgTGVjdHVyYSBkZSBEYXRvcw0KDQpMbyBkYXRvcyBjb3JyZXNwb25kZSBhIHVuYSBtYXRyaXogNXg1eDEwLiBMYSBtZXRhZGF0YSBzZXLDoSBYID0gMS4uLjI1IHkgWiA9IDEuLi4xMCAocHJvZnVuZGlkYWQpLCBhbWJvcyBkZXRlY3RvcmVzIHRpZW5lbiBsYSBtaXNtYSBtZXRhZGF0YS4NCg0KYGBge3J9DQojI01ldGFkYXRhDQpNZXRhZGF0YSA8LSBkYXRhLmZyYW1lKHggPSByZXAoMToxMDAsIGVhY2ggPSAxMSksIA0KICAgICAgICAgICAgICAgICAgICAgICB6ID0gcmVwKDE6MTEsIDEwMCkpDQoNCkNvbXAuZGF0YSA8LSBkYXRhLmZyYW1lKG11ZXN0cmEgPSBjKCJzczQwNiIsICJzczQwNyIsICJzczQwOCIsICJzczQwOSIsICJzczQxMCIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgIEMgPSBjKDAuMTksMC41MCwwLjI4LDAuMTEsMC4zOSksDQogICAgICAgICAgICAgICAgICAgICAgICBNbiA9IGMoMC41MywwLjEzLDAuNjQsMC40OCwwLjQzKSwNCiAgICAgICAgICAgICAgICAgICAgICAgIE5pID0gYygxLjY5LDAuNjEsNC41OCwzLjE0LDIuMDQpLA0KICAgICAgICAgICAgICAgICAgICAgICAgQ3IgPSBjKDIuMTIsMy4wMCwwLjA5LDEuMjIsMS43MiksDQogICAgICAgICAgICAgICAgICAgICAgICBNbyA9IGMoMS4wMywwLjgyLDAuMTQsMC43NywwLjQxKSwNCiAgICAgICAgICAgICAgICAgICAgICAgIEN1ID0gYygwLjMyLDAuNDMsMC43MywwLjIzLDAuNDcpKQ0KYGBgDQoNCiMgREVNT04NCg0KYGBge3J9DQpkYXRhLmRpciA8LSAiRGF0YS9kZW1vbi8iDQoNCiMjIERFTU9OIGRhdGENCkxfRGVtb24gPC0gbWFwKGMoInNzNDA2LmFzYyIsInNzNDA3LmFzYyIsInNzNDA4LmFzYyIsInNzNDA5LmFzYyIsInNzNDEwLmFzYyIpLCANCiAgICAgICAgICAgICAgIH4gcmVhZF90c3YocGFzdGUoZGF0YS5kaXIsLngsc2VwID0gIiIpLCBjb2xfbmFtZXMgPSBGLCBwcm9ncmVzcyA9IEYsIHNob3dfY29sX3R5cGVzID0gRikpIA0KDQpMX0RlbW9uIDwtIExfRGVtb24gJT4lIHNldF9uYW1lcyhjKCJzczQwNiIsInNzNDA3Iiwic3M0MDgiLCJzczQwOSIsInNzNDEwIikpICANCg0KTF9EZW1vbiA8LSBMX0RlbW9uICU+JSBtYXAofiAueCAlPiUgc2V0TmFtZXMoYygid2wiLHBhc3RlKCJYIiwgMToobmNvbCgueCktMSksIHNlcCA9ICIiKSkpKQ0KDQojIyBlbGltaW5hIHNob3QgMQ0KTF9EZW1vbiA8LSBMX0RlbW9uICU+JSANCiAgbWFwKH4gLnggJT4lIC5bLCBjKDEsIHdoaWNoKE1ldGFkYXRhJHogIT0gMSkgKyAxKV0pICMjIGVsaW1pbmEgZGlzcGFybyAjMSAobGltcGllemEpDQoNCmcgPC0gTF9EZW1vbiAlPiUgbWFwKH4gZGF0YS5mcmFtZSgueFssMV0sIEludCA9IGFwcGx5KC54WywyOm5jb2woLngpXSwgMSwgbWVhbikpKSAlPiUgYmluZF9yb3dzKC5pZCA9ICJpZCIpICU+JSANCiAgZ2dwbG90KGFlcyh4ID0gd2wsIHkgPSBJbnQsIGNvbG9yID0gaWQpKSArIGdlb21fbGluZSgpICsgbGFicyh4ID0gIldhdmVsZW5ndGgiKQ0KZyAlPiUgcGxvdGx5OjpnZ3Bsb3RseSgpDQpgYGANCg0KYGBge3J9DQojIyBOb3JtYWxpemFyDQppenEgPC0gMjY3LjcwDQpkZXIgPC0gMjY3Ljc1DQppbnQgPC0gTF9EZW1vbiAlPiUgbWFwX2RmcihmdW4uaW50LCBpenEgPSBpenEsIGRlciA9IGRlcikNCmZhY3RvciA8LSAgMQ0KaW50X25vcm0gPC0gaW50L2ZhY3Rvcg0KDQojIyBhY3VtdWxhcg0KaW50X25vcm0gPC0gc3VtYXJfZmlsYXNfcG9yX2dydXBvcyhpbnRfbm9ybSwgbiA9IDEwLCB3bCA9IEYpDQoNCiMjIFByb21lZGlhcg0KaW50X25vcm0gPC0gY2JpbmQoQ29tcC5kYXRhLCBpbnRfbm9ybSkNCmludF9ub3JtICU+JSBwaXZvdF9sb25nZXIoWDE6WDEwMCwgdmFsdWVzX3RvID0gIkxpYnMuSW50IikgJT4lDQogIGdncGxvdChhZXMoeCA9IExpYnMuSW50LCB5ID0gQ3IsIGNvbG9yID0gbXVlc3RyYSkpICsgDQogICAgZ2VvbV9wb2ludCgpICsgDQogICAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gaW50X25vcm0kQ3IsIGx0eSA9IDIsIGNvbCA9ICJncmF5IikNCg0KaW50X21lYW4gPC0gYXBwbHkoaW50X25vcm0gJT4lIHNlbGVjdChYMTpYMTAwKSwgMSwgcHJvbWVkaWFyX2dydXBvc19hbGVhdG9yaW9zLCBuPTEwKSAlPiUgdCgpICU+JSBkYXRhLmZyYW1lKCkNCmludF9tZWFuIDwtIGNiaW5kKENvbXAuZGF0YSwgaW50X21lYW4pDQppbnRfbWVhbiAlPiUgcGl2b3RfbG9uZ2VyKFgxOlgxMCwgdmFsdWVzX3RvID0gIkxpYnMuSW50IikgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSBMaWJzLkludCwgeSA9IENyLCBjb2xvciA9IG11ZXN0cmEpKSArIA0KICAgIGdlb21fcG9pbnQoKSArIA0KICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IGludF9ub3JtJENyLCBsdHkgPSAyLCBjb2wgPSAiZ3JheSIpDQoNCmludF9tZWFuICU+JSBwaXZvdF9sb25nZXIoWDE6WDEwLCB2YWx1ZXNfdG8gPSAiTGlicy5JbnQiKSAlPiUgDQogIGdncGxvdChhZXMoeCA9IExpYnMuSW50LCB5ID0gQ3IsIGNvbG9yID0gbXVlc3RyYSkpICsgDQogICAgZ2VvbV9ib3hwbG90KCkgKyANCiAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSBpbnRfbm9ybSRDciwgbHR5ID0gMiwgY29sID0gImdyYXkiKQ0KDQpgYGANCiMgTUVDSEVMTEUNCg0KYGBge3J9DQpkYXRhLmRpciA8LSAiRGF0YS9tZWNoZWxsZS8iDQojIyBNZWNoZWxsZSBkYXRhDQpMX01lY2hlbGxlIDwtIG1hcChjKCJzczQwNi5hc2MiLCJzczQwNy5hc2MiLCJzczQwOC5hc2MiLCJzczQwOS5hc2MiLCJzczQxMC5hc2MiKSwgDQogICAgICAgICAgICAgICAgICB+IHJlYWRfdHN2KHBhc3RlKGRhdGEuZGlyLC54LHNlcCA9ICIiKSwgY29sX25hbWVzID0gRiwgcHJvZ3Jlc3MgPSBGLCBzaG93X2NvbF90eXBlcyA9IEYpKSANCg0KTF9NZWNoZWxsZSA8LSBMX01lY2hlbGxlICU+JSBtYXAofiAueCAlPiUgc2V0TmFtZXMoYygid2wiLHBhc3RlKCJYIiwgMToobmNvbCgueCktMSksIHNlcCA9ICIiKSkpKQ0KTF9NZWNoZWxsZSA8LSBMX01lY2hlbGxlICU+JSBzZXRfbmFtZXMoYygic3M0MDYiLCJzczQwNyIsInNzNDA4Iiwic3M0MDkiLCJzczQxMCIpKSAgDQpgYGANCg0KIyMgRXhwbG9yYWNpb24gQ3JvbW8NCg0KYGBge3J9DQojIyBlbGltaW5hIHNob3QgMQ0KTF9NZWNoZWxsZSA8LSBMX01lY2hlbGxlICU+JSANCiAgbWFwKH4gLnggJT4lIC5bLCBjKDEsIHdoaWNoKE1ldGFkYXRhJHogIT0gMSkgKyAxKV0pICMjIGVsaW1pbmEgZGlzcGFybyAjMSAobGltcGllemEpDQoNCmcgPC0gTF9NZWNoZWxsZSAlPiUgbWFwKH4gZGF0YS5mcmFtZSgueFssMV0sIEludCA9IGFwcGx5KC54WywyOm5jb2woLngpXSwgMSwgbWVhbikpKSAlPiUgYmluZF9yb3dzKC5pZCA9ICJpZCIpICU+JSANCiAgZ2dwbG90KGFlcyh4ID0gd2wsIHkgPSBJbnQsIGNvbG9yID0gaWQpKSArIGdlb21fbGluZSgpICsgbGFicyh4ID0gIldhdmVsZW5ndGgiKQ0KZyAlPiUgcGxvdGx5OjpnZ3Bsb3RseSgpDQpgYGANCiMjIFdhdmVsZW5ndGggQ2FsaWJyYXRpb24NCg0KYGBge3J9DQpMX01lY2hlbGxlX25ldyA8LSBMX01lY2hlbGxlICU+JSANCiAgICBtYXAofiBmdW4uV0wuY2FsaWJyYXRpb24ob2xkID0gLngsIHJlZiA9IDQzOC4zMjc1KSkNCg0KDQpnIDwtIExfTWVjaGVsbGUgJT4lIG1hcCh+IGRhdGEuZnJhbWUoLnhbLDFdLCBJbnQgPSBhcHBseSgueFssMjpuY29sKC54KV0sIDEsIG1lYW4pKSkgJT4lIGJpbmRfcm93cyguaWQgPSAiaWQiKSAlPiUgDQogIGdncGxvdChhZXMoeCA9IHdsLCB5ID0gSW50LCBjb2xvciA9IGlkKSkgKyBnZW9tX2xpbmUoKSArIGxhYnMoeCA9ICJXYXZlbGVuZ3RoIikNCmcgJT4lIHBsb3RseTo6Z2dwbG90bHkoKQ0KYGBgDQoNCg0KDQoNCiMjIyBOb3JtYWxpemFuZG8gcG9yIHN1bWEgdG90YWwgMjAwLTEwMDANCg0KQWN1bXVsYXIgKHopIC0gTm9ybWFsaXphciAtIFByb21lZGlhciAoeCkNCg0KYGBge3J9DQojIyBhY3VtdWxhcg0KTCA8LSBMX01lY2hlbGxlICU+JSBtYXAofiAueCAlPiUgc3VtYXJfZmlsYXNfcG9yX2dydXBvcyhuID0gMTApKQ0KICANCiMjIE5vcm1hbGl6YXINCiMgaXpxIDwtIDI2Ny42NTY3DQojIGRlciA8LSAyNjcuODA1Mw0KI2ludCA8LSBMICU+JSBtYXBfZGZyKGZ1bi5pbnQsIGl6cSA9IGl6cSwgZGVyID0gZGVyKQ0KaW50IDwtIEwgJT4lIG1hcF9kZnIoZnVuLmludDIsIGNlbnRybykNCmZhY3RvciA8LSBMICU+JSBtYXBfZGZyKGZ1bi5pbnQsIGl6cSA9IDIwMCwgZGVyID0gMTAzMCkNCmludF9ub3JtIDwtIGludC9mYWN0b3INCg0KIyMgUHJvbWVkaWFyDQppbnRfbm9ybSA8LSBjYmluZChDb21wLmRhdGEsIGludF9ub3JtKQ0KaW50X25vcm0gJT4lIHBpdm90X2xvbmdlcihYMTpYMTAwLCB2YWx1ZXNfdG8gPSAiTGlicy5JbnQiKSAlPiUgZ2dwbG90KGFlcyh4ID0gTGlicy5JbnQsIHkgPSBDciwgY29sb3IgPSBtdWVzdHJhKSkgKyBnZW9tX2JveHBsb3QoKQ0KYGBgDQoNCk5vcm1hbGl6YXIgLSBBY3VtdWxhciAoeikgLSBwcm9tZWRpYXIgKHgpDQoNCmBgYHtyfQ0KIyMgTm9ybWFsaXphcg0KaXpxIDwtIDI2Ny42NTY3DQpkZXIgPC0gMjY3LjgwNTMNCmludCA8LSBMX01lY2hlbGxlICU+JSBtYXBfZGZyKGZ1bi5pbnQsIGl6cSA9IGl6cSwgZGVyID0gZGVyKQ0KZmFjdG9yIDwtIExfTWVjaGVsbGUgJT4lIG1hcF9kZnIoZnVuLmludCwgaXpxID0gMjAwLCBkZXIgPSAxMDMwKQ0KaW50X25vcm0gPC0gaW50L2ZhY3Rvcg0KDQojIyBhY3VtdWxhcg0KaW50X25vcm0gPC0gc3VtYXJfZmlsYXNfcG9yX2dydXBvcyhpbnRfbm9ybSwgbiA9IDEwLCB3bCA9IEYpDQogIA0KIyMgUHJvbWVkaWFyDQppbnRfbm9ybSA8LSBjYmluZChDb21wLmRhdGEsIGludF9ub3JtKQ0KaW50X25vcm0gJT4lIHBpdm90X2xvbmdlcihYMTpYMjUsIHZhbHVlc190byA9ICJMaWJzLkludCIpICU+JSBnZ3Bsb3QoYWVzKHggPSBMaWJzLkludCwgeSA9IENyLCBjb2xvciA9IG11ZXN0cmEpKSArIGdlb21fYm94cGxvdCgpDQpgYGANCiMjIyBOb3JtYWxpemFuZG8gcG9yIHN1bWEgdG90YWwgMjAwLTYwMA0KDQpBY3VtdWxhciAoeikgLSBOb3JtYWxpemFyIC0gUHJvbWVkaWFyICh4KQ0KDQpgYGB7cn0NCiMjIGFjdW11bGFyDQpMIDwtIExfTWVjaGVsbGUgJT4lIG1hcCh+IC54ICU+JSBzdW1hcl9maWxhc19wb3JfZ3J1cG9zKG4gPSAxMCwgd2wgPSBUKSkNCiAgDQojIyBOb3JtYWxpemFyDQppenEgPC0gMjY3LjY1NjcNCmRlciA8LSAyNjcuODA1Mw0KaW50IDwtIEwgJT4lIG1hcF9kZnIoZnVuLmludCwgaXpxID0gaXpxLCBkZXIgPSBkZXIpDQpmYWN0b3IgPC0gTCAlPiUgbWFwX2RmcihmdW4uaW50LCBpenEgPSAyMDAsIGRlciA9IDYwMCkNCmludF9ub3JtIDwtIGludC9mYWN0b3INCg0KIyMgUHJvbWVkaWFyDQppbnRfbm9ybSA8LSBjYmluZChDb21wLmRhdGEsIGludF9ub3JtKQ0KaW50X25vcm0gJT4lIHBpdm90X2xvbmdlcihYMTpYMTAwLCB2YWx1ZXNfdG8gPSAiTGlicy5JbnQiKSAlPiUgDQogIGdncGxvdChhZXMoeCA9IExpYnMuSW50LCB5ID0gQ3IsIGNvbG9yID0gbXVlc3RyYSkpICsgZ2VvbV9ib3hwbG90KCkgKyBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSBpbnRfbm9ybSRDciwgbHR5ID0gMiwgY29sID0gImdyYXkiKQ0KDQppbnRfbWVhbiA8LSBhcHBseShpbnRfbm9ybSAlPiUgc2VsZWN0KFgxOlgxMDApLCAxLCBwcm9tZWRpYXJfZ3J1cG9zX2FsZWF0b3Jpb3MsIG49NSkgJT4lIGRhdGEuZnJhbWUoKQ0KaW50X21lYW4gPC0gY2JpbmQoQ29tcC5kYXRhLCBpbnRfbWVhbikNCmludF9ub3JtICU+JSBwaXZvdF9sb25nZXIoWDE6WDEwLCB2YWx1ZXNfdG8gPSAiTGlicy5JbnQiKSAlPiUgDQogIGdncGxvdChhZXMoeCA9IExpYnMuSW50LCB5ID0gQ3IsIGNvbG9yID0gbXVlc3RyYSkpICsgZ2VvbV9ib3hwbG90KCkgKyBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSBpbnRfbm9ybSRDciwgbHR5ID0gMiwgY29sID0gImdyYXkiKQ0KYGBgDQpOb3JtYWxpemFyIC0gQWN1bXVsYXIgKHopIC0gcHJvbWVkaWFyICh4KQ0KDQpgYGB7cn0NCiMjIE5vcm1hbGl6YXINCml6cSA8LSAyNjcuNjU2Nw0KZGVyIDwtIDI2Ny44MDUzDQppbnQgPC0gTF9NZWNoZWxsZSAlPiUgbWFwX2RmcihmdW4uaW50LCBpenEgPSBpenEsIGRlciA9IGRlcikNCmZhY3RvciA8LSBMX01lY2hlbGxlICU+JSBtYXBfZGZyKGZ1bi5pbnQsIGl6cSA9IDIwMCwgZGVyID0gNjAwKQ0KaW50X25vcm0gPC0gaW50L2ZhY3Rvcg0KDQojIyBhY3VtdWxhcg0KaW50X25vcm0gPC0gc3VtYXJfZmlsYXNfcG9yX2dydXBvcyhpbnRfbm9ybSwgbiA9IDEwLCB3bCA9IEYpDQoNCiMjIFByb21lZGlhcg0KaW50X25vcm0gPC0gY2JpbmQoQ29tcC5kYXRhLCBpbnRfbm9ybSkNCmludF9ub3JtICU+JSBwaXZvdF9sb25nZXIoWDE6WDEwMCwgdmFsdWVzX3RvID0gIkxpYnMuSW50IikgJT4lDQogIGdncGxvdChhZXMoeCA9IExpYnMuSW50LCB5ID0gQ3IsIGNvbG9yID0gbXVlc3RyYSkpICsgZ2VvbV9wb2ludCgpICsgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gaW50X25vcm0kQ3IsIGx0eSA9IDIsIGNvbCA9ICJncmF5IikNCg0KaW50X21lYW4gPC0gYXBwbHkoaW50X25vcm0gJT4lIHNlbGVjdChYMTpYMTAwKSwgMSwgcHJvbWVkaWFyX2dydXBvc19hbGVhdG9yaW9zLCBuPTUpICU+JSBkYXRhLmZyYW1lKCkNCmludF9tZWFuIDwtIGNiaW5kKENvbXAuZGF0YSwgaW50X21lYW4pDQppbnRfbm9ybSAlPiUgcGl2b3RfbG9uZ2VyKFgxOlg1LCB2YWx1ZXNfdG8gPSAiTGlicy5JbnQiKSAlPiUgDQogIGdncGxvdChhZXMoeCA9IExpYnMuSW50LCB5ID0gQ3IsIGNvbG9yID0gbXVlc3RyYSkpICsgZ2VvbV9wb2ludCgpICsgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gaW50X25vcm0kQ3IsIGx0eSA9IDIsIGNvbCA9ICJncmF5IikNCmBgYA0KYGBge3J9DQojIyBOb3JtYWxpemFyDQppenEgPC0gMjgzLjQ5DQpkZXIgPC0gMjgzLjY1DQppbnQgPC0gTF9NZWNoZWxsZSAlPiUgbWFwX2RmcihmdW4uaW50LCBpenEgPSBpenEsIGRlciA9IGRlcikNCmZhY3RvciA8LSBMX01lY2hlbGxlICU+JSBtYXBfZGZyKGZ1bi5pbnQsIGl6cSA9IDIwMCwgZGVyID0gNjAwKQ0KaW50X25vcm0gPC0gaW50L2ZhY3Rvcg0KDQojIyBhY3VtdWxhcg0KaW50X25vcm0gPC0gc3VtYXJfZmlsYXNfcG9yX2dydXBvcyhpbnRfbm9ybSwgbiA9IDEwLCB3bCA9IEYpDQoNCiMjIFByb21lZGlhcg0KaW50X25vcm0gPC0gY2JpbmQoQ29tcC5kYXRhLCBpbnRfbm9ybSkNCmludF9ub3JtICU+JSBwaXZvdF9sb25nZXIoWDE6WDEwMCwgdmFsdWVzX3RvID0gIkxpYnMuSW50IikgJT4lDQogIGdncGxvdChhZXMoeCA9IExpYnMuSW50LCB5ID0gQ3IsIGNvbG9yID0gbXVlc3RyYSkpICsgZ2VvbV9wb2ludCgpICsgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gaW50X25vcm0kQ3IsIGx0eSA9IDIsIGNvbCA9ICJncmF5IikgDQoNCmludF9tZWFuIDwtIGFwcGx5KGludF9ub3JtICU+JSBzZWxlY3QoWDE6WDEwMCksIDEsIHByb21lZGlhcl9ncnVwb3NfYWxlYXRvcmlvcywgbiA9IDUpICU+JSBkYXRhLmZyYW1lKCkNCmludF9tZWFuIDwtIGNiaW5kKENvbXAuZGF0YSwgaW50X21lYW4pDQppbnRfbWVhbiAlPiUgcGl2b3RfbG9uZ2VyKFgxOlg1LCB2YWx1ZXNfdG8gPSAiTGlicy5JbnQiKSAlPiUgDQogIGdncGxvdChhZXMoeCA9IExpYnMuSW50LCB5ID0gQ3IsIGNvbG9yID0gbXVlc3RyYSkpICsgZ2VvbV9wb2ludCgpICsgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gaW50X25vcm0kQ3IsIGx0eSA9IDIsIGNvbCA9ICJncmF5IikNCmBgYA0KDQojIyBFeHBsb3JhY2lvbiBBaXJlIC0gQXJnb24NCg0KYGBge3J9DQpkYXRhLmRpciA8LSAiRGF0YS9leHAxLyINCiMjIE1lY2hlbGxlIGRhdGEgQWlyZQ0KTF9BaXJlIDwtIG1hcChjKCJzczQwN19Ob0JMLmFzYyIsInNzNDA4X05vQkwuYXNjIiksIA0KICAgICAgICAgICAgICAgICAgfiByZWFkX2NzdihwYXN0ZShkYXRhLmRpciwueCxzZXAgPSAiIiksIGNvbF9uYW1lcyA9IEYsIHByb2dyZXNzID0gRiwgc2hvd19jb2xfdHlwZXMgPSBGKSkgJT4lIA0KICBzZXRfbmFtZXMoYygic3M0MDdfQWlyZSIsInNzNDA4X0FpcmUiKSkNCg0KZGF0YS5kaXIgPC0gIkRhdGEvZXhwMi8iDQpMX0FyZ29uIDwtIG1hcChjKCJzczQwN19Bcl9Ob0JMLmFzYyIsInNzNDA4X0FyX05vQkwuYXNjIiksIA0KICAgICAgICAgICAgICAgICAgfiByZWFkX2NzdihwYXN0ZShkYXRhLmRpciwueCxzZXAgPSAiIiksIGNvbF9uYW1lcyA9IEYsIHByb2dyZXNzID0gRiwgc2hvd19jb2xfdHlwZXMgPSBGKSkgJT4lIA0KICBzZXRfbmFtZXMoYygic3M0MDdfQXIiLCJzczQwOF9BciIpKQ0KDQpMX01lY2hlbGxlIDwtIGMoTF9BaXJlLCBMX0FyZ29uKSAlPiUgbWFwKH4gLnggJT4lIHNldE5hbWVzKGMoIndsIixwYXN0ZSgiWCIsIDE6KG5jb2woLngpLTEpLCBzZXAgPSAiIikpKSkNCg0KIyMgTm9ybWFsaXphcg0KaXpxIDwtIDI2Ny42NTY3DQpkZXIgPC0gMjY3LjgwNTMNCmludCA8LSBMX01lY2hlbGxlICU+JSBtYXBfZGZyKGZ1bi5pbnQsIGl6cSA9IGl6cSwgZGVyID0gZGVyKQ0KZmFjdG9yIDwtIExfTWVjaGVsbGUgJT4lIG1hcF9kZnIoZnVuLmludCwgaXpxID0gMjAwLCBkZXIgPSA2MDApDQppbnRfbm9ybSA8LSBpbnQvZmFjdG9yDQoNCiMjIGFjdW11bGFyDQppbnRfbm9ybSA8LSBzdW1hcl9maWxhc19wb3JfZ3J1cG9zKGludF9ub3JtLCBuID0gMjUsIHdsID0gRikNCg0KIyMgUHJvbWVkaWFyDQptZXRkYXRhIDwtIGRhdGEuZnJhbWUobXVlc3RyYSA9IGMoInNzNDA3X0FpcmUiLCAic3M0MDhfQWlyZSIsICJzczQwN19BciIsICJzczQwOF9BciIpKSAlPiUgbXV0YXRlKHJiaW5kKENvbXAuZGF0YVsyOjMsMjpuY29sKENvbXAuZGF0YSldLENvbXAuZGF0YVsyOjMsMjpuY29sKENvbXAuZGF0YSldKSApDQoNCmludF9ub3JtIDwtIGNiaW5kKG1ldGRhdGEsIGludF9ub3JtKQ0KaW50X25vcm0gJT4lIHBpdm90X2xvbmdlcihYMTpYMjUsIHZhbHVlc190byA9ICJMaWJzLkludCIpICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBMaWJzLkludCwgeSA9IENyLCBjb2xvciA9IG11ZXN0cmEpKSArIGdlb21fcG9pbnQoKSArIGdlb21faGxpbmUoeWludGVyY2VwdCA9IGludF9ub3JtJENyLCBsdHkgPSAyLCBjb2wgPSAiZ3JheSIpDQoNCmludF9tZWFuIDwtIGFwcGx5KGludF9ub3JtICU+JSBzZWxlY3QoWDE6WDI1KSwgMSwgcHJvbWVkaWFyX2dydXBvc19hbGVhdG9yaW9zLCBuPTUpICU+JSBkYXRhLmZyYW1lKCkNCmludF9tZWFuIDwtIGNiaW5kKENvbXAuZGF0YSwgaW50X21lYW4pDQppbnRfbm9ybSAlPiUgcGl2b3RfbG9uZ2VyKFgxOlg1LCB2YWx1ZXNfdG8gPSAiTGlicy5JbnQiKSAlPiUgDQogIGdncGxvdChhZXMoeCA9IExpYnMuSW50LCB5ID0gQ3IsIGNvbG9yID0gbXVlc3RyYSkpICsgZ2VvbV9wb2ludCgpICsgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gaW50X25vcm0kQ3IsIGx0eSA9IDIsIGNvbCA9ICJncmF5IikNCmBgYA0KDQoNCg==